/*
 * Copyright (c) 2019.  鼎捷软件股份有限公司.All rights reserved.
 */

package com.digiwin.dap.middleware.util;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 策略id加密
 *
 * @author Seven
 * @date 2019/2/11
 */
public class Base58Encoding {

    private static final String DIGITS = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

    /**
     * Encodes data with a 4-byte checksum
     *
     * @param data Data to be encoded
     * @return String
     */
    public static String encode(byte[] data) {
        return encodePlain(addCheckSum(data));
    }

    /**
     * Encodes data in plain Base58, without any checksum.
     *
     * @param data The data to be encoded
     * @return String
     */
    private static String encodePlain(byte[] data) {
        // Decode byte[] to BigInteger
        BigInteger intData = new BigInteger("0");
        for (byte aData : data) {
            int d = aData & 0xff;
            intData = new BigInteger("256").multiply(intData).add(new BigInteger(d + ""));
        }
        // encode BigInteger to Base58 String
        StringBuilder result = new StringBuilder();
        while (0 != intData.intValue()) {
            BigInteger remainder = intData.mod(new BigInteger("58"));
            intData = intData.divide(new BigInteger("58"));
            result.insert(0, DIGITS.split("")[remainder.intValue()]);
        }
        // Append `1` for each leading 0 byte
        for (int i = 0; i < data.length && data[i] == 0; i++) {
            result.insert(0, '1');
        }
        return result.toString();
    }

    private static byte[] addCheckSum(byte[] data) {
        byte[] checkSum = getCheckSum(data);
        return concatArrays(data, checkSum);
    }

    private static byte[] getCheckSum(byte[] data) {
        byte[] result = new byte[4];
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] hash1 = md.digest(data);
            byte[] hash2 = md.digest(hash1);
            System.arraycopy(hash2, 0, result, 0, result.length);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return result;
    }

    private static byte[] concatArrays(byte[] arr1, byte[] arr2) {
        byte[] result = new byte[arr1.length + arr2.length];
        System.arraycopy(arr1, 0, result, 0, arr1.length);
        System.arraycopy(arr2, 0, result, arr1.length, arr2.length);
        return result;
    }
}
